﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ServiceStack.Redis.Extend
{
    public class RedisClient
    {
        private PooledRedisClientManager mClientManager;

        public RedisClient()
        {
            Init(PooledRedisSection.Instance);
        }

        public RedisClient(string config)
        {
            PooledRedisSection section = (PooledRedisSection)System.Configuration.ConfigurationManager.GetSection(config);
            Init(section);
        }

        private void Init(PooledRedisSection section)
        {
            IList<string> writers = new List<string>();
            foreach (RedisServer item in section.Writers)
            {
                writers.Add(item.Host);
            }
            IList<string> readers = new List<string>();
            foreach (RedisServer item in section.Readers)
            {
                readers.Add(item.Host);
            }
            mClientManager
                = new PooledRedisClientManager(writers, readers, null, section.Db, section.PoolSize, section.PoolTimeOut);
        }

        public PooledRedisClientManager ClientManager
        {
            get
            {
                return mClientManager;
            }
        }

        public T Get<T>(string id) where T : class,new()
        {
            return (T)Get(id, typeof(T));
        }

        public object Get(string id, Type type)
        {
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                return Newtonsoft.Json.JsonConvert.DeserializeObject(
                    client.GetValue(id), type);


            }
        }

        public string GetJson(string id)
        {
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                return client.GetValue(id);


            }
        }

        public int Count(string lstid)
        {
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                return client.GetListCount(lstid);
            }
        }

        public string ListToJson(string lstid)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                List<String> items = client.GetAllItemsFromList(lstid);
                ListToString(items, sb);
            }
            sb.Append("]");
            return sb.ToString();
        }

        private void ListToString(IList<string> items, StringBuilder sb)
        {
            for (int i = 0; i < items.Count; i++)
            {
                if (i > 0)
                    sb.Append(",");
                sb.Append(items[i]);
            }
        }

        public string ListToJson(string lstid, int page, int size)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                List<String> items = client.GetRangeFromList(lstid, page * size, page * size + size - 1);
                ListToString(items, sb);

            }
            sb.Append("]");
            return sb.ToString();
        }

        public System.Collections.IList List(string lstid, Type type)
        {
            System.Type itemstype = System.Type.GetType("System.Collections.Generic.List`1");
            itemstype = itemstype.MakeGenericType(type);
            System.Collections.IList result = (System.Collections.IList)Activator.CreateInstance(itemstype);
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                List<String> items = client.GetAllItemsFromList(lstid);

                for (int i = 0; i < items.Count; i++)
                {
                    result.Add(Newtonsoft.Json.JsonConvert.DeserializeObject(items[i], type));
                }
            }
            return result;
        }

        public System.Collections.IList List(string lstid, int page, int size, Type type)
        {
            System.Type itemstype = System.Type.GetType("System.Collections.Generic.List`1");
            itemstype = itemstype.MakeGenericType(type);
            System.Collections.IList result = (System.Collections.IList)Activator.CreateInstance(itemstype);
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                List<String> items = client.GetRangeFromList(lstid, page * size, page * size + size - 1);

                for (int i = 0; i < items.Count; i++)
                {
                    result.Add(Newtonsoft.Json.JsonConvert.DeserializeObject(items[i], type));
                }
            }
            return result;
        }

        public IList<T> List<T>(string lstid, int page, int size)
        {
            return (IList<T>)List(lstid, page, size, typeof(T));
        }

        public IList<T> List<T>(string lstid) where T : class,new()
        {

            return (IList<T>)List(lstid, typeof(T));
        }

        public void AddToList(string lstid, object value)
        {
            using (IRedisClient client = mClientManager.GetClient())
            {
                client.AddItemToList(lstid, Newtonsoft.Json.JsonConvert.SerializeObject(value));
                client.Save();
            }
        }
        public string PopStringFromList(string listid)
        {
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                
                return client.PopItemFromList(listid);
            }
        }
        public T PopFromList<T>(string listid)
        {

            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(PopStringFromList(listid));


        }
        public void EnqueueToList(string lstid, object value)
        {
            using (IRedisClient client = mClientManager.GetClient())
            {
                client.EnqueueItemOnList(lstid, Newtonsoft.Json.JsonConvert.SerializeObject(value));
                client.Save();
            }
        }

        public void WriteAction(Action<IRedisClient> action)
        {
            using (IRedisClient client = mClientManager.GetClient())
            {
                action(client);
                client.Save();
            }
        }

        public void ReadAction(Action<IRedisClient> action)
        {
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                action(client);

            }
        }

        public void Set(string id, object value)
        {
            using (IRedisClient client = mClientManager.GetClient())
            {
                client.SetEntry(id, Newtonsoft.Json.JsonConvert.SerializeObject(value));
                client.Save();
            }
        }

        public T GetItemFromList<T>(string lstid, int index)
        {
            using (IRedisClient client = mClientManager.GetReadOnlyClient())
            {
                string value = client.GetItemFromList(lstid, index);
                if (string.IsNullOrEmpty(value))
                    return default(T);
                return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(value);
            }
        }

    }
}
